package com.yanqu.road.server.manager.tomb.dao;

import com.fasterxml.jackson.core.type.TypeReference;
import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dao.dbV2.serializer.Helper;
import com.yanqu.road.dao.impl.TempDataObjectDao;
import com.yanqu.road.server.manager.tomb.entity.*;

import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class TombUserDaoImpl extends TempDataObjectDao<DbTombUser> {


    public static TombUserDaoImpl newInstance() {
        TombUserDaoImpl dao = new TombUserDaoImpl();
        return dao;
    }

    public static String updateSql = "update `t_c_activity_tomb_user` set partnerInfoMap=?,partnerUpgradeInfoMap=?,floor=?,x=?,y=?,energy=?,costEnergy=?,energyUpdateTime=?,hp=?,maxHp=?,status=?,attackUserId=?,rewardScore=?,pvpChoseNum=?,userInfo=?,goDownstairs=?,score=?,unionScore=?,multiKill=?,userNianTuNum=?,lockEvent=?,dollMap=?,dollId=?,pvpUnionChooseMap=?,attackAddition=?,hpAddition=?,switchList=?,guideMark=?,assistTimes=?,exploredNum=?,updateTime=?,groupId=? where activityId=? and userId=?";

    @Override
    protected boolean updateData(DbTombUser data) {
        data.setBeginWriteTime();
        getDb().setConnName(DbNameStrategy.getCrossDb());
        int i = 1;
        Map<Integer, DbParameter> dbParameterMap = new HashMap<Integer, DbParameter>();
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getPartnerInfoMap())));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getPartnerUpgradeInfoMap())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getFloor()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getX()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getY()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getEnergy()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getCostEnergy()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getEnergyUpdateTime()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getHp()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getMaxHp()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getStatus()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getAttackUserId()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getRewardScore()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getPvpChoseNum()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getUserInfo())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getGoDownstairs()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getScore()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUnionScore()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getMultiKill()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUserNianTuNum()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, data.getLockEvent()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getDollMap())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getDollId()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getPvpUnionChooseMap())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getAttackAddition()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getHpAddition()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getSwitchList())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getGuideMark()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getAssistTimes()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getExploredNum()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUpdateTime()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getGroupId()));

        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getActivityId()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUserId()));

        if (getDb().executeNoneQuery(updateSql, dbParameterMap) > 0) {
            return true;
        }
        return false;
    }

    public static String insertSql = "insert into `t_c_activity_tomb_user`(activityId,userId,partnerInfoMap,partnerUpgradeInfoMap,floor,x,y,energy,costEnergy,energyUpdateTime,hp,maxHp,status,attackUserId,rewardScore,pvpChoseNum,userInfo,goDownstairs,score,unionScore,multiKill,userNianTuNum,lockEvent,dollMap,dollId,pvpUnionChooseMap,attackAddition,hpAddition,switchList,guideMark,assistTimes,exploredNum,createTime,updateTime,groupId) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";

    @Override
    protected boolean addData(DbTombUser data) {
        data.setBeginWriteTime();
        getDb().setConnName(DbNameStrategy.getCrossDb());
        int i = 1;
        Map<Integer, DbParameter> dbParameterMap = new HashMap<Integer, DbParameter>();
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getActivityId()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUserId()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getPartnerInfoMap())));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getPartnerUpgradeInfoMap())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getFloor()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getX()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getY()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getEnergy()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getCostEnergy()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getEnergyUpdateTime()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getHp()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getMaxHp()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getStatus()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getAttackUserId()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getRewardScore()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getPvpChoseNum()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getUserInfo())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getGoDownstairs()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getScore()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUnionScore()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getMultiKill()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUserNianTuNum()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, data.getLockEvent()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getDollMap())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getDollId()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getPvpUnionChooseMap())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getAttackAddition()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getHpAddition()));
        dbParameterMap.put(i++, new DbParameter(Types.VARCHAR, Helper.toJSONString(data.getSwitchList())));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getGuideMark()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getAssistTimes()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getExploredNum()));

        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getCreateTime()));
        dbParameterMap.put(i++, new DbParameter(Types.BIGINT, data.getUpdateTime()));
        dbParameterMap.put(i++, new DbParameter(Types.INTEGER, data.getGroupId()));
        if (getDb().executeNoneQuery(insertSql, dbParameterMap) > 0) {
            return true;
        }
        return false;
    }


    @Override
    protected DbTombUser parseData(ResultSet rs) throws SQLException {
        DbTombUser data = DbTombUser.newInstance();
        data.setActivityId(rs.getInt("activityId"));
        data.setUserId(rs.getLong("userId"));
        data.setPartnerInfoMap(Helper.toObject(rs.getString("partnerInfoMap"), new TypeReference<ConcurrentHashMap<Integer, PartnerInfo>>(){}));
        if (data.getPartnerInfoMap() == null) {
            data.setPartnerInfoMap(new ConcurrentHashMap<>());
        }
        data.setPartnerUpgradeInfoMap(Helper.toObject(rs.getString("partnerUpgradeInfoMap"), new TypeReference<ConcurrentHashMap<Integer, PartnerUpgradeInfo>>(){}));
        if (data.getPartnerUpgradeInfoMap() == null) {
            data.setPartnerUpgradeInfoMap(new ConcurrentHashMap<>());
        }
        data.setFloor(rs.getInt("floor"));
        data.setX(rs.getInt("x"));
        data.setY(rs.getInt("y"));
        data.setEnergy(rs.getInt("energy"));
        data.setCostEnergy(rs.getInt("costEnergy"));
        data.setEnergyUpdateTime(rs.getLong("energyUpdateTime"));
        data.setHp(rs.getLong("hp"));
        data.setMaxHp(rs.getLong("maxHp"));
        data.setStatus(rs.getInt("status"));
        data.setAttackUserId(rs.getLong("attackUserId"));
        data.setRewardScore(rs.getInt("rewardScore"));
        data.setPvpChoseNum(rs.getInt("pvpChoseNum"));
        data.setUserInfo(Helper.toObject(rs.getString("userInfo"), new TypeReference<UserInfo>(){}));
        if (data.getUserInfo() == null) {
            data.setUserInfo(new UserInfo());
        }
        data.setGoDownstairs(rs.getInt("goDownstairs"));
        data.setScore(rs.getLong("score"));
        data.setUnionScore(rs.getLong("unionScore"));
        data.setMultiKill(rs.getInt("multiKill"));
        data.setUserNianTuNum(rs.getLong("userNianTuNum"));
        data.setLockEvent(rs.getString("lockEvent"));
        data.setDollMap(Helper.toObject(rs.getString("dollMap"), new TypeReference<ConcurrentHashMap<Integer, Long>>(){}));
        if (data.getDollMap() == null) {
            data.setDollMap(new ConcurrentHashMap<>());
        }
        data.setDollId(rs.getInt("dollId"));
        data.setPvpUnionChooseMap(Helper.toObject(rs.getString("pvpUnionChooseMap"), new TypeReference<HashSet<String>>(){}));
        if (data.getPvpUnionChooseMap() == null) {
            data.setPvpUnionChooseMap(new HashSet<>());
        }
        data.setAttackAddition(rs.getInt("attackAddition"));
        data.setHpAddition(rs.getInt("hpAddition"));
        data.setSwitchList(Helper.toObject(rs.getString("switchList"), new TypeReference<ArrayList<Integer>>(){}));
        if (data.getSwitchList() == null) {
            data.setSwitchList(new ArrayList<>());
        }

        data.setGuideMark(rs.getInt("guideMark"));
        data.setAssistTimes(rs.getInt("assistTimes"));
        data.setExploredNum(rs.getInt("exploredNum"));

        data.setCreateTime(rs.getLong("createTime"));
        data.setUpdateTime(rs.getLong("updateTime"));
        data.setGroupId(rs.getInt("groupId"));

        return data;
    }

    public DbTombUser getData(int activityId, long userId) {
        ResultSet rs = null;
        CallableStatement call = null;
        String selectSql = "select * from t_c_activity_tomb_user where activityId = ? and userId = ?";
        try {
            getDb().setConnName(DbNameStrategy.getCrossDb());
            call = getDb().getConnection().prepareCall(selectSql);
            call.setInt(1, activityId);
            call.setLong(2, userId);
            rs = call.executeQuery();
            if (rs.next()) {
                return parse(rs);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return null;
    }

    public Map<Long, DbTombUser> getDataMap(int activityId) {
        ResultSet rs = null;
        CallableStatement call = null;
        Map<Long, DbTombUser> dataMap = new ConcurrentHashMap<>();
        String selectSql = "select * from t_c_activity_tomb_user where activityId = ?";
        try {
            getDb().setConnName(DbNameStrategy.getCrossDb());
            call = getDb().getConnection().prepareCall(selectSql);
            call.setInt(1, activityId);
            rs = call.executeQuery();
            while (rs.next()) {
                DbTombUser data = parse(rs);
                dataMap.put(data.getUserId(), data);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return dataMap;
    }

    public boolean saveData(DbTombUser data) {
        if (data.isUpdateOption()) {
            if (data.isNeedInsert()) {
                if (addData(data)) {
                    data.setNeedInsert(false);
                }
            } else {
                data.setUpdateTime(System.currentTimeMillis());
                update(data);
            }
        }
        return true;
    }

}
